/**
 * 
 */
package it.nola.soccer;

import java.util.ArrayList;
import java.util.List;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

/**
 * Classe che contiene tutte le interazioni con il db
 * 
 * @author paolo
 */
public class DbHelper {
    private static class DatabaseHelper extends SQLiteOpenHelper {
	DatabaseHelper(Context context) {
	    super(context, Const.DATABASE_NAME, null, DATABASE_VERSION);
	}

	/**
	 * La prima cosa da fare quando il db è creato è creare le tabelle dell'applicazione
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
	    db.execSQL("create table "+Const.Cronache.NAME+"(_id integer primary key autoincrement, "
		+Const.Cronache.KEY_TITLE+" text not null, "+Const.Cronache.KEY_BODY+" text not null, "
		+Const.Cronache.KEY_TEAM1+" text not null, "+Const.Cronache.KEY_ASSISTENTS+" text null, "
		+Const.Cronache.KEY_REFEREE+" text not null, "+Const.Cronache.KEY_RESULT+" text not null, "
		+Const.Cronache.KEY_TEAM2+" text not null, "+Const.Cronache.KEY_PLACE+" text not null, "
		+Const.Cronache.KEY_MATCH_DATE+" text not null,"+Const.Cronache.KEY_PLAYER_NR
		+" integer not null default 0);");
	    db.execSQL("create table "+Const.Players.NAME+"(_id integer primary key autoincrement, "
		+Const.Players.KEY_CRONACA+" integer not null, "+Const.Players.KEY_NR+" string not null, "
		+Const.Players.KEY_NAME+" text not null, "+Const.Players.KEY_TEAM+" integer not null,"
		+Const.Players.KEY_IS_MR+" integer not null default 0,"+Const.Players.KEY_IS_FC
		+" integer not null default 1);");
	    db.execSQL("create table "+Const.Subst.NAME+"(_id integer primary key autoincrement, "
		+Const.Subst.KEY_CRONACA+" integer not null, "+Const.Subst.KEY_PLAYER_IN+" integer not null, "
		+Const.Subst.KEY_PLAYER_OUT+" integer not null, "+Const.Subst.KEY_MIN+" string not null, "
		+Const.Subst.KEY_HALF+" integer not null, "+Const.Subst.KEY_TEAM+" integer not null);");
	    db.execSQL("create table "+Const.Actions.NAME+"(_id integer primary key autoincrement, "
		+Const.Actions.KEY_CRONACA+" integer not null, "+Const.Actions.KEY_DESCRI+" string not null, "
		+Const.Actions.KEY_MIN+" string not null, "+Const.Actions.KEY_HALF+" integer not null, "
		+Const.Actions.KEY_TEAM+" integer null);");
	    db.execSQL("create table "+Const.Cards.NAME+"(_id integer primary key autoincrement, "
		+Const.Cards.KEY_CRONACA+" integer not null, "+Const.Cards.KEY_PLAYER+" integer not null, "
		+Const.Cards.KEY_MIN+" string not null, "+Const.Cards.KEY_HALF+" integer not null, "
		+Const.Cards.KEY_CARD+" integer not null,"+Const.Cards.KEY_REASON+" string null,"+Const.Cards.KEY_TEAM
		+" integer null);");
	    db.execSQL("create table "+Const.Goals.NAME+"(_id integer primary key autoincrement, "
		+Const.Goals.KEY_CRONACA+" integer not null, "+Const.Goals.KEY_PLAYER+" integer not null, "
		+Const.Goals.KEY_MIN+" string not null, "+Const.Goals.KEY_IS_AUTO+" integer not null, "
		+Const.Goals.KEY_IS_PENALTY+" integer not null, "+Const.Goals.KEY_HALF+" integer not null, "
		+Const.Goals.KEY_TEAM+" integer not null);");
	    db.execSQL("create table "+Const.Config.NAME+"("+Const.Config.KEY_MAIL_TO+" string not null, "
		+Const.Config.KEY_MAIL_FROM+" string not null, "+Const.Config.KEY_DEFAULT_PL_NUMBER
		+" integer not null);");
	    ContentValues args=new ContentValues();
	    args.put(Const.Config.KEY_DEFAULT_PL_NUMBER, 0);
	    args.put(Const.Config.KEY_MAIL_TO, "info@soccer-notes.com");
	    args.put(Const.Config.KEY_MAIL_FROM, "info@soccer-notes.com");
	    db.insert(Const.Config.NAME, null, args);
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
	    Log.w(TAG, "Upgrading database from version "+oldVersion+" to "+newVersion
		+", which will destroy all old data");
	    // onCreate(db);
	}
    }

    public static final String KEY_TITOLI="TITOLI";
    private static final String TAG="NotesDbAdapter";
    private DatabaseHelper mDbHelper;

    private SQLiteDatabase mDb;

    private static final int DATABASE_VERSION=2;

    private final Context mCtx;

    /**
     * Il costruttore - prende il contesto per permettergli di creare / aprire il db
     * 
     * @param ctx : il contesto in cui lavorare
     */
    public DbHelper(Context ctx) {
	this.mCtx=ctx;

    }

    /**
     * @param cronaca : la cronaca da controllare
     * @return true se ci sono giocatori per entrambe le squadre, false altrimenti
     */
    public boolean areThereAnyPlayer(Long cronaca) {
	if (cronaca==null) {
	    return false;
	}
	Cursor c=mDb.query(Const.Players.NAME, new String[]{Const.Players.KEY_ROWID }, Const.Players.KEY_CRONACA+"="
	    +cronaca+" AND "+Const.Players.KEY_TEAM+"="+Const.HOME_TEAM, null, null, null, null);
	if (!c.moveToFirst()) {
	    c.close();
	    return false;
	}
	c=mDb.query(Const.Players.NAME, new String[]{Const.Players.KEY_ROWID }, Const.Players.KEY_CRONACA+"="+cronaca
	    +" AND "+Const.Players.KEY_TEAM+"="+Const.FOREIGN_TEAM, null, null, null, null);
	boolean ret=c.moveToFirst();
	c.close();
	return ret;
    }

    /**
     * Cancella l'azione selezionata
     * 
     * @param rowId: l'id dell'azione
     */
    public void cancellaAction(long rowId) {
	mDb.delete(Const.Actions.NAME, Const.Actions.KEY_ROWID+"="+rowId, null);
    }

    /**
     * Cancella il cartellino
     * 
     * @param rowId: l'id del cartellino
     */
    public void cancellaCard(long rowId) {
	mDb.delete(Const.Cards.NAME, Const.Cards.KEY_ROWID+"="+rowId, null);
    }

    /**
     * Cancella il goal
     * 
     * @param rowId: l'id del goal
     */
    public void cancellaGoal(long rowId) {
	mDb.delete(Const.Goals.NAME, Const.Goals.KEY_ROWID+"="+rowId, null);
    }

    /**
     * Cancella la sostituzione
     * 
     * @param rowId: l'id della sostituzione
     */
    public void cancellaSubst(long rowId) {
	mDb.delete(Const.Subst.NAME, Const.Subst.KEY_ROWID+"="+rowId, null);
    }

    /**
     * Cerca le azioni di una cronaca
     * 
     * @param cronaca: l'id della cronaca
     * @return
     */
    public Cursor cercaAction(long cronaca) {
	return mDb.rawQuery("SELECT "+Const.Actions.KEY_ROWID+", "+Const.Actions.KEY_TEAM+", "+Const.Actions.KEY_HALF
	    +", "+Const.Actions.KEY_DESCRI+","+Const.Actions.KEY_MIN+" FROM "+Const.Actions.NAME+" WHERE "
	    +Const.Actions.KEY_CRONACA+"="+cronaca+" ORDER BY "+Const.Actions.KEY_ROWID+" DESC", null);
    }

    /**
     * Cerca tutti i cartellini di una cronaca
     * 
     * @param cronaca: l'id della cronaca
     * @return
     */
    public Cursor cercaCard(long cronaca) {
	return mDb.rawQuery("SELECT c._id AS "+Const.Cards.KEY_ROWID+", p."+Const.Players.KEY_NAME+" AS "
	    +Const.Cards.KEY_NAME_PLAYER+", c."+Const.Cards.KEY_TEAM+" AS "+Const.Cards.KEY_TEAM+", "
	    +Const.Cards.KEY_HALF+", "+Const.Cards.KEY_CARD+","+Const.Cards.KEY_REASON+","+Const.Cards.KEY_MIN+" FROM "
	    +Const.Cards.NAME+" AS c JOIN "+Const.Players.NAME+" AS p ON "+Const.Cards.KEY_PLAYER+"=p."
	    +Const.Players.KEY_ROWID+" WHERE c."+Const.Players.KEY_CRONACA+"="+cronaca+" ORDER BY c."
	    +Const.Cards.KEY_ROWID+" DESC", null);
    }

    /**
     * Recupera dal db i parametri i configurazione
     * 
     * @return Un cursore con i parametri
     */
    public Cursor cercaConfig() {
	return mDb.query(Const.Config.NAME, Const.Config.ALL_FIELDS, null, null, null, null, null);
    }

    /**
     * Cerca i goal di una cronaca
     * 
     * @param cronaca: l'id della cronaca
     * @return
     */
    public Cursor cercaGoal(long cronaca) {
	return mDb.rawQuery("SELECT g._id AS "+Const.Goals.KEY_ROWID+", p."+Const.Players.KEY_NAME+" AS "
	    +Const.Goals.KEY_NAME_PLAYER+", g."+Const.Goals.KEY_TEAM+" AS "+Const.Goals.KEY_TEAM+", "
	    +Const.Goals.KEY_HALF+", "+Const.Goals.KEY_IS_AUTO+","+Const.Goals.KEY_MIN+","+Const.Goals.KEY_IS_PENALTY
	    +" FROM "+Const.Goals.NAME+" AS g JOIN "+Const.Players.NAME+" AS p ON "+Const.Goals.KEY_PLAYER+"=p."
	    +Const.Players.KEY_ROWID+" WHERE g."+Const.Players.KEY_CRONACA+"="+cronaca+" ORDER BY g."
	    +Const.Goals.KEY_ROWID+" DESC", null);
    }

    /**
     * Verifica se esiste in archivio una squadra con il dato nome
     * 
     * @param nomeSquadra
     * @return un cursors con id della cronache e i nomi delle due squadre
     */
    private Cursor cercaOldCronaca(String nomeSquadra, Long actCronaca) {
	return mDb.query(Const.Cronache.NAME, new String[]{Const.Cronache.KEY_ROWID, Const.Cronache.KEY_TEAM1,
	    Const.Cronache.KEY_TEAM2 }, "("+Const.Cronache.KEY_TEAM1+"=?"+" OR "+Const.Cronache.KEY_TEAM2+"=?) AND "
	    +Const.Cronache.KEY_ROWID+"<>?", new String[]{nomeSquadra, nomeSquadra, actCronaca.toString() }, null,
	    null, Const.Cronache.KEY_ROWID+" DESC");
    }

    /**
     * @param squadra : 1 (squadra di casa) o 2 (squadra in trasferta)
     * @param cronaca : l'id della cronaca per la quale cerchiamo la formazione
     * @return un cursore che contiente DbConst.players.MAX_PLAYERS righe
     */
    public Cursor cercaSquadra(short squadra, long cronaca) {
	return mDb.query(Const.Players.NAME, Const.Players.ALL_FIELDS, Const.Players.KEY_CRONACA+"="+cronaca+" AND "
	    +Const.Players.KEY_TEAM+"="+squadra, null, null, null, Const.Players.KEY_ROWID+" ASC");
    }

    /**
     * Cerca le sostituzioni di una cronaca
     * 
     * @param cronaca: l'id della cronaca
     * @return
     */
    public Cursor cercaSubst(long cronaca) {
	return mDb.rawQuery("SELECT s._id AS "+Const.Subst.KEY_ROWID+",s."+Const.Subst.KEY_TEAM+" AS "
	    +Const.Subst.KEY_TEAM+", team_in."+Const.Players.KEY_NAME+" AS "+Const.Subst.KEY_NAME_PLAYER_IN
	    +", team_out."+Const.Players.KEY_NAME+" AS "+Const.Subst.KEY_NAME_PLAYER_OUT+", "+Const.Subst.KEY_HALF+","
	    +Const.Subst.KEY_MIN+" FROM "+Const.Subst.NAME+" AS s, "+Const.Players.NAME+" AS team_in, "
	    +Const.Players.NAME+" AS team_out WHERE "+Const.Subst.KEY_PLAYER_IN+"=team_in._id AND "
	    +Const.Subst.KEY_PLAYER_OUT+"=team_out._id AND s."+Const.Players.KEY_CRONACA+"="+cronaca+" ORDER BY s."
	    +Const.Subst.KEY_ROWID+" DESC", null);
    }

    public List<String> cercaVecchieSquadre(String constr) {
	List<String> ret=new ArrayList<String>();
	Cursor c=mDb.rawQuery("Select team1 from cronache where team1 like '"+constr
	    +"%' UNION Select team2 from cronache where team2 like '"+constr+"%'", null);
	if (c.moveToFirst()) {
	    do {
		if (!ret.contains(c.getString(0))) {
		    ret.add(c.getString(0));
		    if (ret.size()==Const.MAX_SUGGESTIONS) {
			break;
		    }
		}
	    }
	    while (c.moveToNext());
	}
	c.close();
	return ret;
    }

    /**
     * Chiude la connessione con il db
     */
    public void close() {
	mDbHelper.close();
    }

    /**
     * Crea una nuova cronaca usando le informazioni passate. Se la nota è creata con successo the
     * note is successfully created return the new rowId for that note, otherwise return a -1 to
     * indicate failure.
     * 
     * @param title the title of the note
     * @param notes the body of the note
     * @param result
     * @param referee
     * @param assistent2
     * @param assistent1
     * @param place
     * @param nrPlayers
     * @team1: il nome della squadra di casa
     * @team2: il nome della squadra in trasferta
     * @md: la data dell'incontro
     * @return rowId or -1 if failed
     */
    public long createNote(String title, String notes, String team1, String team2, String md, String assistents,
	String referee, String result, String place, Long nrPlayers) {
	ContentValues args=new ContentValues();
	args.put(Const.Cronache.KEY_TITLE, title);
	args.put(Const.Cronache.KEY_BODY, notes);
	args.put(Const.Cronache.KEY_MATCH_DATE, md);
	args.put(Const.Cronache.KEY_TEAM1, team1);
	args.put(Const.Cronache.KEY_TEAM2, team2);
	args.put(Const.Cronache.KEY_ASSISTENTS, assistents);
	args.put(Const.Cronache.KEY_REFEREE, referee);
	args.put(Const.Cronache.KEY_RESULT, result);
	args.put(Const.Cronache.KEY_PLACE, place);
	args.put(Const.Cronache.KEY_PLAYER_NR, nrPlayers);
	return mDb.insert(Const.Cronache.NAME, null, args);
    }

    /**
     * Cancella una nota con chiave rowId
     * 
     * @param rowId : id della cronaca da cancellare
     * @return true se cancellata, false altrimenti
     */
    public boolean deleteNote(long rowId) {
	return mDb.delete(Const.Cronache.NAME, Const.Cronache.KEY_ROWID+"="+rowId, null)>0;
    }

    /**
     * Restituisce un Cursor che si muove sulla lista di tutte le cronache in db
     * 
     * @return Cursor delle cronache
     */
    public Cursor fetchAllNotes() {
	return mDb.query(Const.Cronache.NAME, Const.Cronache.ALL_FIELDS, null, null, null, null, null);
    }

    /**
     * Resituisce un elenco di titoli
     * 
     * @return
     */
    public Cursor fetchAllTitles() {
	return mDb.rawQuery("SELECT "+Const.Cronache.KEY_ROWID+", "+Const.Cronache.KEY_TEAM1+"|| ' - ' || "
	    +Const.Cronache.KEY_TEAM2+" || ' ' || "+Const.Cronache.KEY_RESULT+" AS "+KEY_TITOLI+" FROM "
	    +Const.Cronache.NAME+" ORDER BY "+Const.Cronache.KEY_ROWID+" DESC", null);
    }

    /**
     * Restituisce tutti i giocatori di una squadra e di una cronaca, sulla base dei filtri
     * 
     * @param cronaca: la cronaca cui si fa riferimento
     * @param squadra: 0 o 1
     * @param is_from_bench: se true mostra prima i panchinari
     * @param filter_mister: se true non mostra l'allenatore
     * @return un cursore con la coppia _id - (nr + nome del giocatore) ordinato sulla base del
     *         campo IS_FC e NR; può filtrare l'allenatore.
     */
    public Cursor getAllPlayers(long cronaca, int squadra, boolean is_from_bench, boolean filter_mister) {
	String order=is_from_bench ? " ASC," : " DESC,";
	String filtroMister=filter_mister ? " AND "+Const.Players.KEY_IS_MR+"=0" : "";
	return mDb.rawQuery("Select "+Const.Players.KEY_ROWID+", "+Const.Players.KEY_NR+"||' - '||"
	    +Const.Players.KEY_NAME+" AS "+Const.Players.KEY_NAME+" FROM "+Const.Players.NAME+" WHERE "
	    +Const.Players.KEY_CRONACA+"="+cronaca+" AND "+Const.Players.KEY_TEAM+"="+squadra+filtroMister+" ORDER BY "
	    +Const.Players.KEY_IS_FC+order+Const.Players.KEY_NR+" ASC", null);
    }

    /**
     * Inserimento nel db dell'azione
     * 
     * @param team: 0 o 1
     * @param half: 0,1,2,3 o4
     * @param min: il minuto
     * @param cronaca: la cronaca cui appartiene la cronaca
     * @param descri: la descrizione della cronaca
     */
    public void insertAction(int team, int half, String min, long cronaca, String descri) {
	ContentValues args=new ContentValues();
	args.put(Const.Actions.KEY_DESCRI, descri);
	args.put(Const.Actions.KEY_CRONACA, cronaca);
	args.put(Const.Actions.KEY_HALF, half);
	args.put(Const.Actions.KEY_MIN, min);
	args.put(Const.Actions.KEY_TEAM, team);
	mDb.insert(Const.Actions.NAME, null, args);
    }

    public void insertCard(long player, int team, int half, String min, long cronaca, String motivo, int card) {
	ContentValues args=new ContentValues();
	args.put(Const.Cards.KEY_PLAYER, player);
	args.put(Const.Cards.KEY_REASON, motivo);
	args.put(Const.Cards.KEY_CRONACA, cronaca);
	args.put(Const.Cards.KEY_HALF, half);
	args.put(Const.Cards.KEY_MIN, min);
	args.put(Const.Cards.KEY_TEAM, team);
	args.put(Const.Cards.KEY_CARD, card);
	mDb.insert(Const.Cards.NAME, null, args);
    }

    public void insertGoal(long player, int team, int half, String min, long cronaca, boolean isAuto, boolean isRigore) {
	ContentValues args=new ContentValues();
	int isAutoNum=isAuto ? 1 : 0;
	int isRigNum=isRigore ? 1 : 0;
	args.put(Const.Goals.KEY_PLAYER, player);
	args.put(Const.Goals.KEY_IS_AUTO, isAutoNum);
	args.put(Const.Goals.KEY_CRONACA, cronaca);
	args.put(Const.Goals.KEY_HALF, half);
	args.put(Const.Goals.KEY_MIN, min);
	args.put(Const.Goals.KEY_TEAM, team);
	args.put(Const.Goals.KEY_IS_PENALTY, isRigNum);
	mDb.insert(Const.Goals.NAME, null, args);
    }

    /**
     * Inserimento di una sostituzione
     * 
     * @param player_in
     * @param player_out
     * @param team
     * @param half
     * @param min
     * @param cronaca
     */
    public void insertSubst(long player_in, long player_out, int team, int half, String min, long cronaca) {
	ContentValues args=new ContentValues();
	args.put(Const.Subst.KEY_PLAYER_IN, player_in);
	args.put(Const.Subst.KEY_PLAYER_OUT, player_out);
	args.put(Const.Subst.KEY_CRONACA, cronaca);
	args.put(Const.Subst.KEY_HALF, half);
	args.put(Const.Subst.KEY_MIN, min);
	args.put(Const.Subst.KEY_TEAM, team);
	mDb.insert(Const.Subst.NAME, null, args);
    }

    /**
     * Open the notes database. If it cannot be opened, try to create a new instance of the
     * database. If it cannot be created, throw an exception to signal the failure
     * 
     * @return this (self reference, allowing this to be chained in an initialization call)
     * @throws SQLException if the database could be neither opened or created
     */
    public DbHelper open() throws SQLException {
	mDbHelper=new DatabaseHelper(mCtx);
	mDb=mDbHelper.getWritableDatabase();
	return this;
    }

    /**
     * Recupera una singola azione
     * 
     * @param id: l'id dell'azione
     * @return
     */
    public Cursor recuperaAction(long id) {
	return mDb.query(Const.Actions.NAME, Const.Actions.ALL_FIELDS, Const.Actions.KEY_ROWID+"="+id, null, null,
	    null, null);
    }

    /**
     * recupera il singolo cartellino
     * 
     * @param id: l'id del cartellino
     * @return
     */
    public Cursor recuperaCard(long id) {
	return mDb
	    .query(Const.Cards.NAME, Const.Cards.ALL_FIELDS, Const.Cards.KEY_ROWID+"="+id, null, null, null, null);
    }

    /**
     * Recupera tutti i dati relativi ad una cronaca
     * 
     * @param id: l'id della cronaca
     * @return un cursore con la cronaca
     */
    public Cursor recuperaCronaca(Long id) {
	return mDb.query(Const.Cronache.NAME, Const.Cronache.ALL_FIELDS, Const.Cronache.KEY_ROWID+"="+id, null, null,
	    null, null);
    }

    public Cursor recuperaGoal(long id) {
	return mDb
	    .query(Const.Goals.NAME, Const.Goals.ALL_FIELDS, Const.Goals.KEY_ROWID+"="+id, null, null, null, null);
    }

    public Cursor recuperaSubst(long id) {
	return mDb
	    .query(Const.Subst.NAME, Const.Subst.ALL_FIELDS, Const.Subst.KEY_ROWID+"="+id, null, null, null, null);
    }

    public String recuperaTitolo(long id) {
	Cursor c=mDb.rawQuery("SELECT "+Const.Cronache.KEY_TEAM1+"|| ' - ' || "+Const.Cronache.KEY_TEAM2+" || ' ' || "
	    +Const.Cronache.KEY_RESULT+" AS "+KEY_TITOLI+" FROM "+Const.Cronache.NAME, null);
	if (c.moveToFirst()) {
	    String ret=c.getString(c.getColumnIndex(KEY_TITOLI));
	    c.close();
	    return ret;
	}
	c.close();
	return null;
    }

    /**
     * Funzione di utilità che crea una squadra di default e resituisce un cursore che punta alla
     * squadra appena creata. Cerca, sulla base del nome della squadra, l'esistenza di precedenti
     * righe nel db: se esistono, copia i valori dell'ultima cronaca nella nuova, altrimenti salva
     * valori di default (numeri da 1 a nrPlayers e nomi vuoti)
     * 
     * @param squadra: 0 o 1
     * @param cronaca: la cronaca i ncui salvare la squadra
     * @param nomeSquadra: il nome della squadra
     * @param nrPlayers: il numero di giocatori da inserire
     * @return
     */
    public Cursor riempiSqadra(short squadra, long cronaca, String nomeSquadra, int nrPlayers) {
	Cursor oldCronaca=cercaOldCronaca(nomeSquadra, cronaca);
	if (oldCronaca.moveToFirst()) {
	    // caso a: c'era già una cronaca che parlava della stessa squadra
	    short oldTeam=nomeSquadra.equals(oldCronaca.getString(oldCronaca.getColumnIndex(Const.Cronache.KEY_TEAM1))) ? Const.HOME_TEAM
		: Const.FOREIGN_TEAM;
	    // carico i giocatori della vecchia squadra
	    Cursor c=cercaSquadra(oldTeam, oldCronaca.getLong(oldCronaca.getColumnIndex(Const.Cronache.KEY_ROWID)));
	    int i=1;
	    while (c.moveToNext()) {
		/**
		 * Abbio 3 casi possibili:
		 * <ul>
		 * <li>a1) Il numero di giocatori vecchio è uguale a quello attuale => nessun
		 * problema
		 * <li>a2) i vecchi giocatori sono in numero inferiore a quello attuale => devo
		 * riempire con giocatori di default</li>
		 * <li>a3) il vecchi giocatori sono in numero superiore a quello attuale => arrivato
		 * a nrPlayers mi devo fermare e copiare direttamente il mister
		 */
		ContentValues args=new ContentValues();
		if (c.getShort(c.getColumnIndex(Const.Players.KEY_IS_MR))==1) {
		    // sono nel caso a2) => procedo al riempimento
		    for (; i<=nrPlayers; i++) {
			args.put(Const.Players.KEY_CRONACA, cronaca);
			args.put(Const.Players.KEY_NAME, "");
			args.put(Const.Players.KEY_NR, i);
			args.put(Const.Players.KEY_IS_MR, 0);
			args.put(Const.Players.KEY_IS_FC, 0);
			args.put(Const.Players.KEY_TEAM, squadra);
			mDb.insert(Const.Players.NAME, null, args);
		    }
		    // quindi prendo il mister e ho finito
		    args.put(Const.Players.KEY_CRONACA, cronaca);
		    args.put(Const.Players.KEY_TEAM, squadra);
		    args.put(Const.Players.KEY_NAME, c.getString(c.getColumnIndex(Const.Players.KEY_NAME)));
		    args.put(Const.Players.KEY_NR, c.getString(c.getColumnIndex(Const.Players.KEY_NR)));
		    args.put(Const.Players.KEY_IS_MR, c.getShort(c.getColumnIndex(Const.Players.KEY_IS_MR)));
		    args.put(Const.Players.KEY_IS_FC, c.getShort(c.getColumnIndex(Const.Players.KEY_IS_FC)));
		    mDb.insert(Const.Players.NAME, null, args);
		}
		else {
		    args.put(Const.Players.KEY_CRONACA, cronaca);
		    args.put(Const.Players.KEY_TEAM, squadra);
		    args.put(Const.Players.KEY_NAME, c.getString(c.getColumnIndex(Const.Players.KEY_NAME)));
		    args.put(Const.Players.KEY_NR, c.getString(c.getColumnIndex(Const.Players.KEY_NR)));
		    args.put(Const.Players.KEY_IS_MR, c.getShort(c.getColumnIndex(Const.Players.KEY_IS_MR)));
		    args.put(Const.Players.KEY_IS_FC, c.getShort(c.getColumnIndex(Const.Players.KEY_IS_FC)));
		    mDb.insert(Const.Players.NAME, null, args);
		}
		if (i==nrPlayers) {
		    // ho caricato l'ultimo giocatore: devo caricare il mister e ho finito
		    // va bene sia nel caso a1 (il c.moveToLast() equivale ad un c.moveToNext()) sia
		    // al caso a2 (in quel caso il c.moveToLast() salta i giocatori in più)
		    c.moveToLast();
		    args=new ContentValues();
		    args.put(Const.Players.KEY_CRONACA, cronaca);
		    args.put(Const.Players.KEY_TEAM, squadra);
		    args.put(Const.Players.KEY_NAME, c.getString(c.getColumnIndex(Const.Players.KEY_NAME)));
		    args.put(Const.Players.KEY_NR, c.getString(c.getColumnIndex(Const.Players.KEY_NR)));
		    args.put(Const.Players.KEY_IS_MR, c.getShort(c.getColumnIndex(Const.Players.KEY_IS_MR)));
		    args.put(Const.Players.KEY_IS_FC, c.getShort(c.getColumnIndex(Const.Players.KEY_IS_FC)));
		    mDb.insert(Const.Players.NAME, null, args);
		    break;
		}
		i++;
	    }
	}
	else {
	    int toInsert=nrPlayers+1; // devo inseriro n+1 righe (n=nr giocatori + l'allenatore)
	    for (int i=1; i<=toInsert; i++) {
		ContentValues args=new ContentValues();
		args.put(Const.Players.KEY_CRONACA, cronaca);
		args.put(Const.Players.KEY_NAME, "");
		if (i!=toInsert) {
		    args.put(Const.Players.KEY_NR, i);
		    args.put(Const.Players.KEY_IS_MR, 0);
		    if (i<Const.NR_TITOLARI) {
			args.put(Const.Players.KEY_IS_FC, 1);
		    }
		    else {
			args.put(Const.Players.KEY_IS_FC, 0);
		    }
		}
		else {
		    args.put(Const.Players.KEY_NR, mCtx.getString(R.string.coach));
		    args.put(Const.Players.KEY_IS_MR, 0);
		}
		args.put(Const.Players.KEY_TEAM, squadra);
		mDb.insert(Const.Players.NAME, null, args);
	    }
	}
	Cursor ret=cercaSquadra(squadra, cronaca);
	return ret;
    }

    public void updateAction(long rowId, int team, int half, String min, long cronaca, String descri) {
	ContentValues args=new ContentValues();
	args.put(Const.Actions.KEY_CRONACA, cronaca);
	args.put(Const.Actions.KEY_DESCRI, descri);
	args.put(Const.Actions.KEY_TEAM, team);
	args.put(Const.Actions.KEY_HALF, half);
	args.put(Const.Actions.KEY_MIN, min);
	mDb.update(Const.Actions.NAME, args, Const.Actions.KEY_ROWID+"="+rowId, null);
    }

    public void updateCard(long rowId, long player, int team, int half, String min, long cronaca, String motivo,
	int card) {
	ContentValues args=new ContentValues();
	args.put(Const.Cards.KEY_CRONACA, cronaca);
	args.put(Const.Cards.KEY_PLAYER, player);
	args.put(Const.Cards.KEY_REASON, motivo);
	args.put(Const.Cards.KEY_TEAM, team);
	args.put(Const.Cards.KEY_HALF, half);
	args.put(Const.Cards.KEY_MIN, min);
	args.put(Const.Cards.KEY_CARD, card);
	mDb.update(Const.Cards.NAME, args, Const.Goals.KEY_ROWID+"="+rowId, null);
    }

    public void updateConfig(long nrPl, String mailTo, String mailFrom) {
	ContentValues args=new ContentValues();
	args.put(Const.Config.KEY_DEFAULT_PL_NUMBER, nrPl);
	args.put(Const.Config.KEY_MAIL_FROM, mailFrom);
	args.put(Const.Config.KEY_MAIL_TO, mailTo);
	mDb.update(Const.Config.NAME, args, null, null);

    }

    public void updateGoal(long rowId, long player, int team, int half, String min, long cronaca, boolean isAuto,
	boolean isRigore) {
	ContentValues args=new ContentValues();
	int isAutoNum=isAuto ? 1 : 0;
	int isRigNum=isRigore ? 1 : 0;
	args.put(Const.Goals.KEY_CRONACA, cronaca);
	args.put(Const.Goals.KEY_PLAYER, player);
	args.put(Const.Goals.KEY_IS_AUTO, isAutoNum);
	args.put(Const.Goals.KEY_TEAM, team);
	args.put(Const.Goals.KEY_HALF, half);
	args.put(Const.Goals.KEY_MIN, min);
	args.put(Const.Goals.KEY_IS_PENALTY, isRigNum);
	mDb.update(Const.Goals.NAME, args, Const.Goals.KEY_ROWID+"="+rowId, null);
    }

    /**
     * Aggiorna la cronaca usando i dettagli forniti. The note to be updated is specified using the
     * rowId, and it is altered to use the title and body values passed in
     * 
     * @param rowId id of note to update
     * @param title value to set note title to
     * @param body value to set note body to
     * @return true if the note was successfully updated, false otherwise
     */
    public boolean updateNote(long rowId, String title, String body, String date, String team1, String team2,
	String assistents, String referee, String result, String luogo) {
	ContentValues args=new ContentValues();
	args.put(Const.Cronache.KEY_TITLE, title);
	args.put(Const.Cronache.KEY_BODY, body);
	args.put(Const.Cronache.KEY_MATCH_DATE, date);
	args.put(Const.Cronache.KEY_TEAM1, team1);
	args.put(Const.Cronache.KEY_TEAM2, team2);
	args.put(Const.Cronache.KEY_ASSISTENTS, assistents);
	args.put(Const.Cronache.KEY_REFEREE, referee);
	args.put(Const.Cronache.KEY_RESULT, result);
	args.put(Const.Cronache.KEY_PLACE, luogo);
	return mDb.update(Const.Cronache.NAME, args, Const.Cronache.KEY_ROWID+"="+rowId, null)>0;
    }

    /**
     * Aggiornamento di un giocatore
     * 
     * @param rowId: l'id del giocatore
     * @param squadra: 0 o 1
     * @param cronaca: la cronaca di appartenenza
     * @param nr: il numero di maglia
     * @param nome: il nome e cognome del giocatore
     * @param is_mr: 1 se è l'allenatore, 0 altrimenti
     * @param is_fc: 1 se è titolare, 0 altrimenti
     */
    public void updatePlayer(long rowId, short squadra, long cronaca, String nr, String nome, int is_mr, int is_fc) {
	ContentValues args=new ContentValues();
	args.put(Const.Players.KEY_CRONACA, cronaca);
	args.put(Const.Players.KEY_NAME, nome);
	args.put(Const.Players.KEY_NR, nr);
	args.put(Const.Players.KEY_TEAM, squadra);
	args.put(Const.Players.KEY_IS_FC, is_fc);
	args.put(Const.Players.KEY_IS_MR, is_mr);
	mDb.update(Const.Players.NAME, args, Const.Players.KEY_ROWID+"="+rowId, null);
    }

    /**
     * Aggiornamento di una sostituzione
     * 
     * @param parseLong
     * @param player_in
     * @param player_out
     * @param team
     * @param half
     * @param min
     * @param cronaca
     */
    public void updateSubst(long rowId, long player_in, long player_out, int team, int half, String min, long cronaca) {
	ContentValues args=new ContentValues();
	args.put(Const.Subst.KEY_CRONACA, cronaca);
	args.put(Const.Subst.KEY_PLAYER_IN, player_in);
	args.put(Const.Subst.KEY_PLAYER_OUT, player_out);
	args.put(Const.Subst.KEY_TEAM, team);
	args.put(Const.Subst.KEY_HALF, half);
	args.put(Const.Subst.KEY_MIN, min);
	mDb.update(Const.Subst.NAME, args, Const.Subst.KEY_ROWID+"="+rowId, null);
    }
}
